package drds.plus.sql_process.type;

import drds.plus.sql_process.type.impl.*;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Comparator;

/**
 * http://dev.mysql.com/doc/refman/5.6/en/type-conversion.html
 *
 * <pre>
 * 类型信息主要针对两类
 * a. 字段  【数据库结构里可以获取】
 * b. 函数
 *    1. Dummy函数 (下推) 【返回null，由应用基于返回值调用{@linkplain Types}进行动态获取】
 *    2. tddl自实现 【以函数的第一个字段的类型为准，嵌套函数时递归获取第一个字段】
 *
 * 针对特殊的函数，比如select 1+1, 没有字段信息，默认以LongType处理，
 * ps. mysql中string的加法也是按照数字来处理, 比如 selectStatement "a" + "b" = 2 ,  selectStatement "1" + "a" = 1
 * </pre>
 */
public interface Type<Value> extends Comparator<Object> {

    // 自定义一个year sqlType
    int YEAR_SQL_TYPE = 10001;
    int UNDECIDED_SQL_TYPE = 10099; // 未决类型

    Type<Integer> IntegerType = new IntegerType();
    Type<Long> LongType = new LongType();
    Type<Short> ShortType = new ShortType();
    Type<String> StringType = new StringType();
    Type<Double> DoubleType = new DoubleType();
    Type<Float> FloatType = new FloatType();
    Type<Boolean> BooleanType = new BooleanType();
    Type<BigInteger> BigIntegerType = new BigIntegerType();
    Type<BigDecimal> BigDecimalType = new BigDecimalType();

    Type<Date> DateType = new DateType();
    Type<Timestamp> TimestampType = new TimestampType();
    Type<Timestamp> DatetimeType = new TimestampType();
    Type<Time> TimeType = new TimeType();
    Type<Long> YearType = new LongType();

    //Type<byte[]> BlobType = new BlobType();
    //Type<String> ClobType = new ClobType();

    Type<Integer> BitType = new BitType();
    Type<BigDecimal> BigBitType = new BigBitType();
    //Type<byte[]> BytesType = new BytesType();
    Type<Byte> ByteType = new ByteType();
    Type UndecidedType = new UndecidedType();
    Type IntervalType = new IntervalType();
    Type NullType = UndecidedType;

    ResultGetter getResultGetter();

    /**
     * @return encode之后的byte[]的length
     */
    int encode(Object value, byte[] bytes, int offset);

    /**
     * encode之后的byte[]的length
     */
    int getLength(Object value);

    DecodeResult decode(byte[] bytes, int offset);

    /**
     * 针对数据类型获取开区间的下一条
     */
    Value incr(Object value);

    /**
     * 针对数据类型获取开区间的下一条
     */
    Value decr(Object value);

    /**
     * 对应数据类型的最大值
     */
    Value getMaxValue();

    /**
     * 对应数据类型的最小值
     */
    Value getMinValue();

    /**
     * 将数据转化为当前DataType类型
     */
    Value convert(Object value);

    /**
     * 数据类型对应的class
     */
    Class getValueClass();

    /**
     * 数据计算器
     */
    Calculator getCalculator();

    /**
     * 获取类型对应的jdbcType
     */
    int getSqlType();

}
